extensions: add a double extension
authorØyvind Kolås <pippin@gimp.org>
Thu, 5 Apr 2018 21:24:31 +0000 (23:24 +0200)
committerØyvind Kolås <pippin@gimp.org>
Thu, 5 Apr 2018 21:24:34 +0000 (23:24 +0200)
This will permit slightly faster than the generic fast paths for some possibly
desired intermediate conversions. This also adds alpha stripping - which fills
in the last babl fast path currently reported missing on every launch of GIMP.

extensions/Makefile.am
extensions/double.c [new file with mode: 0644]
extensions/gggl-table-lies.c
extensions/gggl-table.c
extensions/meson.build
extensions/two-table.c

index b103c93fc88a6271fc4c5bedfa1ab55ef518a828..06d6bea7d4da21b3e376e7afd12aa2af58aa65b6 100644 (file)
@@ -18,7 +18,7 @@ ext_LTLIBRARIES = \
        16bit.la        \
        cairo.la        \
        CIE.la          \
-    float-half.la   \
+       float-half.la   \
        gegl-fixups.la  \
        gggl-lies.la    \
        gggl-table.la   \
@@ -26,6 +26,7 @@ ext_LTLIBRARIES = \
        gggl.la         \
        gimp-8bit.la    \
        grey.la         \
+       double.la       \
        float.la        \
        fast-float.la   \
        naive-CMYK.la   \
diff --git a/extensions/double.c b/extensions/double.c
new file mode 100644 (file)
index 0000000..f592cb9
--- /dev/null
@@ -0,0 +1,264 @@
+/* babl - dynamically extendable universal pixel conversion library.
+ * Copyright (C) 2012, Øyvind Kolås
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "babl-internal.h"
+#include "babl-cpuaccel.h"
+#include "extensions/util.h"
+#include "base/util.h"
+
+
+#define INLINE inline
+
+
+static INLINE void
+conv_rgbaD_linear_rgbAD_gamma (const Babl *conversion,unsigned char *src,
+                               unsigned char *dst,
+                               long           samples)
+{
+   const Babl  *space = babl_conversion_get_destination_space (conversion);
+   const Babl **trc   = (void*)space->space.trc;
+
+   double *fsrc = (double *) src;
+   double *fdst = (double *) dst;
+   int n = samples;
+
+   while (n--)
+     {
+       double alpha = fsrc[3];
+       *fdst++ = babl_trc_from_linear (trc[0], *fsrc++) * alpha;
+       *fdst++ = babl_trc_from_linear (trc[1], *fsrc++) * alpha;
+       *fdst++ = babl_trc_from_linear (trc[2], *fsrc++) * alpha;
+       *fdst++ = *fsrc++;
+     }
+}
+
+static INLINE void
+conv_rgbAD_linear_rgbAD_gamma (const Babl    *conversion,
+                               unsigned char *src,
+                               unsigned char *dst,
+                               long           samples)
+{
+   const Babl  *space = babl_conversion_get_destination_space (conversion);
+   const Babl **trc   = (void*)space->space.trc;
+
+   double *fsrc = (double *) src;
+   double *fdst = (double *) dst;
+   int n = samples;
+
+   while (n--)
+     {
+       double alpha = fsrc[3];
+       if (alpha < BABL_ALPHA_THRESHOLD)
+         {
+           *fdst++ = 0.0;
+           *fdst++ = 0.0;
+           *fdst++ = 0.0;
+           *fdst++ = 0.0;
+           fsrc+=4;
+         }
+       else if (alpha >= 1.0)
+         {
+           *fdst++ = babl_trc_from_linear (trc[0], *fsrc++) * alpha;
+           *fdst++ = babl_trc_from_linear (trc[1], *fsrc++) * alpha;
+           *fdst++ = babl_trc_from_linear (trc[2], *fsrc++) * alpha;
+           *fdst++ = *fsrc++;
+         }
+       else
+         {
+           double alpha_recip = 1.0 / alpha;
+           *fdst++ = babl_trc_from_linear (trc[0], *fsrc++ * alpha_recip) * alpha;
+           *fdst++ = babl_trc_from_linear (trc[1], *fsrc++ * alpha_recip) * alpha;
+           *fdst++ = babl_trc_from_linear (trc[2], *fsrc++ * alpha_recip) * alpha;
+           *fdst++ = *fsrc++;
+         }
+     }
+}
+
+static INLINE void
+conv_rgbaD_linear_rgbaD_gamma (const Babl *conversion,unsigned char *src, 
+                               unsigned char *dst, 
+                               long           samples)
+{
+   const Babl  *space = babl_conversion_get_destination_space (conversion);
+   const Babl **trc   = (void*)space->space.trc;
+
+   double *fsrc = (double *) src;
+   double *fdst = (double *) dst;
+   int n = samples;
+
+   while (n--)
+     {
+       *fdst++ = babl_trc_from_linear (trc[0], *fsrc++);
+       *fdst++ = babl_trc_from_linear (trc[1], *fsrc++);
+       *fdst++ = babl_trc_from_linear (trc[2], *fsrc++);
+       *fdst++ = *fsrc++;
+     }
+}
+
+#define conv_rgbaD_linear_rgbD_linear conv_rgbaD_gamma_rgbD_gamma
+
+static void
+conv_rgbaD_linear_rgbD_linear (const Babl *conversion,unsigned char *src,
+                               unsigned char *dst,
+                               long           samples)
+{
+   double *fsrc = (double *) src;
+   double *fdst = (double *) dst;
+   int n = samples;
+
+   while (n--)
+     {
+       *fdst++ = *fsrc++;
+       *fdst++ = *fsrc++;
+       *fdst++ = *fsrc++;
+       fsrc++;
+     }
+}
+
+
+static INLINE void
+conv_rgbD_linear_rgbD_gamma (const Babl *conversion,unsigned char *src, 
+                             unsigned char *dst, 
+                             long           samples)
+{
+   const Babl  *space = babl_conversion_get_destination_space (conversion);
+   const Babl **trc   = (void*)space->space.trc;
+   double *fsrc = (double *) src;
+   double *fdst = (double *) dst;
+   int n = samples;
+
+   while (n--)
+     {
+       *fdst++ = babl_trc_from_linear (trc[0], *fsrc++);
+       *fdst++ = babl_trc_from_linear (trc[1], *fsrc++);
+       *fdst++ = babl_trc_from_linear (trc[2], *fsrc++);
+     }
+}
+
+
+static INLINE void
+conv_rgbaD_gamma_rgbaD_linear (const Babl *conversion,unsigned char *src, 
+                               unsigned char *dst, 
+                               long           samples)
+{
+   const Babl  *space = babl_conversion_get_destination_space (conversion);
+   const Babl **trc   = (void*)space->space.trc;
+   double *fsrc = (double *) src;
+   double *fdst = (double *) dst;
+   int n = samples;
+
+   while (n--)
+     {
+       *fdst++ = babl_trc_to_linear (trc[0], *fsrc++);
+       *fdst++ = babl_trc_to_linear (trc[1], *fsrc++);
+       *fdst++ = babl_trc_to_linear (trc[2], *fsrc++);
+       *fdst++ = *fsrc++;
+     }
+}
+
+static INLINE void
+conv_rgbD_gamma_rgbD_linear (const Babl *conversion,unsigned char *src, 
+                             unsigned char *dst, 
+                             long           samples)
+{
+   const Babl  *space = babl_conversion_get_destination_space (conversion);
+   const Babl **trc   = (void*)space->space.trc;
+   double *fsrc = (double *) src;
+   double *fdst = (double *) dst;
+   int n = samples;
+
+   while (n--)
+     {
+       *fdst++ = babl_trc_to_linear (trc[0], *fsrc++);
+       *fdst++ = babl_trc_to_linear (trc[1], *fsrc++);
+       *fdst++ = babl_trc_to_linear (trc[2], *fsrc++);
+     }
+}
+
+#define o(src, dst) \
+  babl_conversion_new (src, dst, "linear", conv_ ## src ## _ ## dst, NULL)
+
+int init (void);
+
+int
+init (void)
+{
+  const Babl *rgbaD_linear = babl_format_new (
+    babl_model ("RGBA"),
+    babl_type ("double"),
+    babl_component ("R"),
+    babl_component ("G"),
+    babl_component ("B"),
+    babl_component ("A"),
+    NULL);
+  const Babl *rgbAD_linear = babl_format_new (
+    babl_model ("RaGaBaA"),
+    babl_type ("double"),
+    babl_component ("Ra"),
+    babl_component ("Ga"),
+    babl_component ("Ba"),
+    babl_component ("A"),
+    NULL);
+  const Babl *rgbaD_gamma = babl_format_new (
+    babl_model ("R'G'B'A"),
+    babl_type ("double"),
+    babl_component ("R'"),
+    babl_component ("G'"),
+    babl_component ("B'"),
+    babl_component ("A"),
+    NULL);
+  const Babl *rgbAD_gamma = babl_format_new (
+    babl_model ("R'aG'aB'aA"),
+    babl_type ("double"),
+    babl_component ("R'a"),
+    babl_component ("G'a"),
+    babl_component ("B'a"),
+    babl_component ("A"),
+    NULL);
+  const Babl *rgbD_linear = babl_format_new (
+    babl_model ("RGB"),
+    babl_type ("double"),
+    babl_component ("R"),
+    babl_component ("G"),
+    babl_component ("B"),
+    NULL);
+  const Babl *rgbD_gamma = babl_format_new (
+    babl_model ("R'G'B'"),
+    babl_type ("double"),
+    babl_component ("R'"),
+    babl_component ("G'"),
+    babl_component ("B'"),
+    NULL);
+
+  o (rgbAD_linear, rgbAD_gamma);
+  o (rgbaD_linear, rgbAD_gamma);
+  o (rgbaD_linear, rgbaD_gamma);
+  o (rgbaD_gamma,  rgbaD_linear);
+  o (rgbD_linear, rgbD_gamma);
+  o (rgbD_gamma,  rgbD_linear);
+  o (rgbaD_linear, rgbD_linear);
+  o (rgbaD_gamma,  rgbD_gamma);
+
+  return 0;
+}
+
index 6cce2ba1f5e5b7f9199a352ac600bfc59614b9ef..88da9b64c6eb380780a97cf6da1444276e4daa63 100644 (file)
@@ -302,6 +302,38 @@ conv_ga16_gaF (const Babl *conversion,unsigned char *src, unsigned char *dst, lo
 #define conv_gA16_gAF        conv_ga16_gaF
 #define conv_g16_gF          conv_16_F
 
+static void
+conv_rgbafloat_linear_cairo32_le (const Babl *conversion,unsigned char *src_char,
+                                  unsigned char *dst,
+                                  long           samples)
+{
+  long   n    = samples;
+  float *src  = (float*)src_char;
+
+  while (n--)
+    {
+      float alpha = src[3] * 255;
+#define BABL_ALPHA_THRESHOLD 0.000000152590219
+
+      if (alpha < BABL_ALPHA_THRESHOLD)
+        {
+          *(int *)dst = 0;
+        }
+      else
+        {
+          if (alpha > 255) alpha = 255;
+#define div_255(a) ((((a)+128)+(((a)+128)>>8))>>8)
+          dst[0] = src[2] * alpha + 0.5f;
+          dst[1] = src[1] * alpha + 0.5f;
+          dst[2] = src[0] * alpha + 0.5f;
+          dst[3] = alpha + 0.5f;
+        }
+      src += 4;
+      dst += 4;
+    }
+}
+
+
 int init (void);
 
 int
@@ -428,6 +460,26 @@ init (void)
     babl_component ("Y"),
     NULL);
 
+  int   testint  = 23;
+  char *testchar = (char*) &testint;
+  int   littleendian = (testchar[0] == 23);
+
+  if (littleendian)
+    {
+      const Babl *f32 = babl_format_new (
+        "name", "cairo-ARGB32",
+        babl_model ("R'aG'aB'aA"),
+        babl_type ("u8"),
+        babl_component ("B'a"),
+        babl_component ("G'a"),
+        babl_component ("R'a"),
+        babl_component ("A"),
+        NULL
+      );
+      babl_conversion_new (babl_format ("RGBA float"), f32, "linear",
+                           conv_rgbafloat_linear_cairo32_le, NULL);
+  }
+
 #define o(src, dst) \
   babl_conversion_new (src, dst, "linear", conv_ ## src ## _ ## dst, NULL)
 
index 0ce0353e0876d17213c38fce0403fb948aaa6b66..37d68dc62b42a22978704f5ee614636f91d0ddad 100644 (file)
@@ -164,6 +164,7 @@ conv_F_8 (const Babl *conversion,unsigned char *src, unsigned char *dst, long sa
     }
 }
 
+
 static void
 conv_F_16 (const Babl *conversion,unsigned char *src, unsigned char *dst, long samples)
 {
index d04ad671a2db87008e41f0579c4e417dab6bc982..f452417584aacfb8a770710d1be2448d70f7673a 100644 (file)
@@ -2,6 +2,7 @@ extension_names = [
   '16bit',
   'cairo',
   'CIE',
+  'double',
   'fast-float',
   'float-half',
   'float',
index 4b263ccb1435465187933fcc9bc68b03efaf8865..880adff30f56e485b57b7da9aa8b74c60572ea83 100644 (file)
@@ -205,6 +205,17 @@ init (void)
 
   if (littleendian)
     {
+      const Babl *f32 = babl_format_new (
+        "name", "cairo-ARGB32",
+        babl_model ("R'aG'aB'aA"),
+        babl_type ("u8"),
+        babl_component ("B'a"),
+        babl_component ("G'a"),
+        babl_component ("R'a"),
+        babl_component ("A"),
+        NULL
+      );
+
       const Babl *f24 = babl_format_new (
         "name", "cairo-RGB24",
         babl_model ("R'G'B'"),